<?php

declare(strict_types=1);

use think\facade\Db;
use think\migration\Migrator;

class SeedAuthRolesAndPermissions extends Migrator
{
    public function up(): void
    {
        $now = date('Y-m-d H:i:s');

        $permissions = $this->permissions();
        Db::name('auth_permission')
            ->whereIn('code', array_column($permissions, 'code'))
            ->delete();
        foreach ($permissions as $permission) {
            Db::name('auth_permission')->insert([
                'name' => $permission['name'],
                'code' => $permission['code'],
                'description' => $permission['description'],
                'client_type' => $permission['client_type'],
                'status' => 1,
                'create_time' => $now,
                'update_time' => $now,
            ]);
        }

        $roles = $this->roles();
        Db::name('auth_role')
            ->whereIn('slug', array_column($roles, 'slug'))
            ->delete();

        $roleIds = [];
        foreach ($roles as $role) {
            $roleIds[$role['slug']] = Db::name('auth_role')->insertGetId([
                'name' => $role['name'],
                'slug' => $role['slug'],
                'scope_type' => $role['scope_type'],
                'description' => $role['description'],
                'status' => 1,
                'create_time' => $now,
                'update_time' => $now,
            ]);
        }

        $permissionMap = Db::name('auth_permission')
            ->column('id', 'code');

        foreach ($this->rolePermissionMap() as $roleSlug => $codes) {
            if (!isset($roleIds[$roleSlug])) {
                continue;
            }
            $roleId = $roleIds[$roleSlug];
            Db::name('auth_role_perm')->where('role_id', $roleId)->delete();
            foreach ($codes as $code) {
                if (!isset($permissionMap[$code])) {
                    continue;
                }
                Db::name('auth_role_perm')->insert([
                    'role_id' => $roleId,
                    'permission_id' => (int) $permissionMap[$code],
                    'create_time' => $now,
                    'update_time' => $now,
                ]);
            }
        }

        $this->seedAdminUser($roleIds['admin'] ?? null, $permissionMap);
    }

    public function down(): void
    {
        $codes = array_column($this->permissions(), 'code');
        Db::name('auth_permission')->whereIn('code', $codes)->delete();

        $slugs = array_column($this->roles(), 'slug');
        $roleIds = Db::name('auth_role')->whereIn('slug', $slugs)->column('id');
        if ($roleIds) {
            Db::name('auth_role_perm')->whereIn('role_id', $roleIds)->delete();
            Db::name('auth_user_role')->whereIn('role_id', $roleIds)->delete();
        }
        Db::name('auth_role')->whereIn('slug', $slugs)->delete();
    }

    private function permissions(): array
    {
        return [
            ['code' => 'admin.user.account.view', 'name' => '账户查看', 'description' => '查看系统账户列表', 'client_type' => 'admin'],
            ['code' => 'admin.user.account.manage', 'name' => '账户维护', 'description' => '新增、编辑、删除系统账户', 'client_type' => 'admin'],
            ['code' => 'admin.user.role.view', 'name' => '角色查看', 'description' => '查看系统角色', 'client_type' => 'admin'],
            ['code' => 'admin.user.role.manage', 'name' => '角色维护', 'description' => '维护系统角色权限', 'client_type' => 'admin'],
            ['code' => 'admin.user.permission.view', 'name' => '权限查看', 'description' => '查看权限列表', 'client_type' => 'admin'],

            ['code' => 'admin.org.org.view', 'name' => '组织查看', 'description' => '查看组织档案', 'client_type' => 'admin'],
            ['code' => 'admin.org.org.manage', 'name' => '组织维护', 'description' => '维护组织档案', 'client_type' => 'admin'],
            ['code' => 'admin.org.member.view', 'name' => '成员查看', 'description' => '查看组织成员', 'client_type' => 'admin'],
            ['code' => 'admin.org.member.manage', 'name' => '成员维护', 'description' => '维护组织成员', 'client_type' => 'admin'],
            ['code' => 'admin.org.audit.view', 'name' => '组织审核查看', 'description' => '查看企业/个人审核', 'client_type' => 'admin'],
            ['code' => 'admin.org.audit.update', 'name' => '组织审核处理', 'description' => '处理企业/个人审核', 'client_type' => 'admin'],

            ['code' => 'admin.region.view', 'name' => '区域查看', 'description' => '查看区域列表', 'client_type' => 'admin'],
            ['code' => 'admin.region.manage', 'name' => '区域维护', 'description' => '维护区域数据', 'client_type' => 'admin'],

            ['code' => 'admin.product.category.view', 'name' => '类目查看', 'description' => '查看商品类目', 'client_type' => 'admin'],
            ['code' => 'admin.product.category.manage', 'name' => '类目维护', 'description' => '维护商品类目', 'client_type' => 'admin'],
            ['code' => 'admin.product.brand.view', 'name' => '品牌查看', 'description' => '查看品牌', 'client_type' => 'admin'],
            ['code' => 'admin.product.brand.manage', 'name' => '品牌维护', 'description' => '维护品牌', 'client_type' => 'admin'],
            ['code' => 'admin.product.item.view', 'name' => '商品查看', 'description' => '查看商品资料', 'client_type' => 'admin'],
            ['code' => 'admin.product.item.manage', 'name' => '商品维护', 'description' => '维护商品资料', 'client_type' => 'admin'],

            ['code' => 'admin.order.main.view', 'name' => '订单查看', 'description' => '查看订单', 'client_type' => 'admin'],
            ['code' => 'admin.order.main.update', 'name' => '订单维护', 'description' => '维护订单状态', 'client_type' => 'admin'],
            ['code' => 'admin.order.pickup.view', 'name' => '揽件查看', 'description' => '查看揽件任务', 'client_type' => 'admin'],
            ['code' => 'admin.order.pickup.update', 'name' => '揽件维护', 'description' => '维护揽件任务', 'client_type' => 'admin'],
            ['code' => 'admin.order.refund.view', 'name' => '售后查看', 'description' => '查看售后/退款', 'client_type' => 'admin'],
            ['code' => 'admin.order.refund.update', 'name' => '售后处理', 'description' => '处理售后/退款', 'client_type' => 'admin'],
            ['code' => 'admin.order.invoice.view', 'name' => '发票查看', 'description' => '查看发票对账', 'client_type' => 'admin'],
            ['code' => 'admin.order.invoice.update', 'name' => '发票审核', 'description' => '处理发票对账', 'client_type' => 'admin'],

            ['code' => 'admin.finance.commission.view', 'name' => '佣金查看', 'description' => '查看佣金规则', 'client_type' => 'admin'],
            ['code' => 'admin.finance.commission.manage', 'name' => '佣金维护', 'description' => '维护佣金规则', 'client_type' => 'admin'],
            ['code' => 'admin.finance.settlement.view', 'name' => '结算查看', 'description' => '查看结算单', 'client_type' => 'admin'],
            ['code' => 'admin.finance.settlement.manage', 'name' => '结算处理', 'description' => '处理结算单', 'client_type' => 'admin'],
            ['code' => 'admin.finance.platform.view', 'name' => '平台资金查看', 'description' => '查看平台账户', 'client_type' => 'admin'],
            ['code' => 'admin.finance.platform.manage', 'name' => '平台资金维护', 'description' => '调整平台资金', 'client_type' => 'admin'],

            ['code' => 'admin.tms.pickup.view', 'name' => '物流揽件查看', 'description' => '查看物流揽件', 'client_type' => 'admin'],
            ['code' => 'admin.tms.pickup.manage', 'name' => '物流揽件维护', 'description' => '维护物流揽件', 'client_type' => 'admin'],
            ['code' => 'admin.tms.trace.view', 'name' => '物流轨迹查看', 'description' => '查看物流轨迹', 'client_type' => 'admin'],
            ['code' => 'admin.tms.trace.manage', 'name' => '物流轨迹维护', 'description' => '维护物流轨迹', 'client_type' => 'admin'],
            ['code' => 'admin.tms.express.view', 'name' => '快递维护查看', 'description' => '查看快递公司信息', 'client_type' => 'admin'],
            ['code' => 'admin.tms.express.manage', 'name' => '快递维护', 'description' => '维护快递公司信息', 'client_type' => 'admin'],

            ['code' => 'admin.notify.template.view', 'name' => '通知模板查看', 'description' => '查看通知模板', 'client_type' => 'admin'],
            ['code' => 'admin.notify.template.manage', 'name' => '通知模板维护', 'description' => '维护通知模板', 'client_type' => 'admin'],
            ['code' => 'admin.notify.record.view', 'name' => '通知记录查看', 'description' => '查看通知发送记录', 'client_type' => 'admin'],
            ['code' => 'admin.notify.record.resend', 'name' => '通知重发', 'description' => '重发通知消息', 'client_type' => 'admin'],

            ['code' => 'admin.system.config.view', 'name' => '系统配置查看', 'description' => '查看系统配置', 'client_type' => 'admin'],
            ['code' => 'admin.system.config.manage', 'name' => '系统配置维护', 'description' => '维护系统配置', 'client_type' => 'admin'],
            ['code' => 'admin.system.menu.view', 'name' => '菜单查看', 'description' => '查看菜单结构', 'client_type' => 'admin'],
            ['code' => 'admin.system.menu.manage', 'name' => '菜单维护', 'description' => '维护菜单结构', 'client_type' => 'admin'],
            ['code' => 'admin.system.log.view', 'name' => '操作日志查看', 'description' => '查看后台操作日志', 'client_type' => 'admin'],
            ['code' => 'admin.system.log.export', 'name' => '操作日志导出', 'description' => '导出后台操作日志', 'client_type' => 'admin'],

            ['code' => 'admin.support.task.view', 'name' => '任务中心查看', 'description' => '查看任务中心', 'client_type' => 'support'],
            ['code' => 'admin.support.task.assign', 'name' => '任务分配', 'description' => '抢单或分配任务', 'client_type' => 'support'],
            ['code' => 'admin.support.invite.view', 'name' => '邀请记录查看', 'description' => '查看邀请记录与邀请码', 'client_type' => 'support'],
            ['code' => 'admin.support.invite.manage', 'name' => '邀请维护', 'description' => '维护邀请码', 'client_type' => 'support'],

            ['code' => 'seller.trade.spotcheck.view', 'name' => '卖家现货核实查看', 'description' => '查看现货核实', 'client_type' => 'seller'],
            ['code' => 'seller.trade.spotcheck.manage', 'name' => '卖家现货核实处理', 'description' => '处理现货核实', 'client_type' => 'seller'],
            ['code' => 'seller.trade.future.view', 'name' => '卖家期货询价查看', 'description' => '查看期货询价', 'client_type' => 'seller'],
            ['code' => 'seller.trade.future.manage', 'name' => '卖家期货询价处理', 'description' => '处理期货询价', 'client_type' => 'seller'],
            ['code' => 'seller.trade.order_delivery.view', 'name' => '订单发货查看', 'description' => '查看订单发货', 'client_type' => 'seller'],
            ['code' => 'seller.trade.order_delivery.manage', 'name' => '订单发货处理', 'description' => '处理订单发货', 'client_type' => 'seller'],
            ['code' => 'seller.product.list.view', 'name' => '商品列表查看', 'description' => '查看商品列表', 'client_type' => 'seller'],
            ['code' => 'seller.product.list.manage', 'name' => '商品列表维护', 'description' => '维护商品资料', 'client_type' => 'seller'],
            ['code' => 'seller.product.upload.view', 'name' => '商品上传查看', 'description' => '访问批量上传', 'client_type' => 'seller'],
            ['code' => 'seller.product.upload.manage', 'name' => '商品上传维护', 'description' => '执行批量上传', 'client_type' => 'seller'],
            ['code' => 'seller.fund.statement.view', 'name' => '结算单查看', 'description' => '查看卖家结算单', 'client_type' => 'seller'],
            ['code' => 'seller.fund.statement.manage', 'name' => '结算单维护', 'description' => '确认结算单', 'client_type' => 'seller'],
            ['code' => 'seller.setting.role.view', 'name' => '卖家角色查看', 'description' => '查看角色', 'client_type' => 'seller'],
            ['code' => 'seller.setting.role.manage', 'name' => '卖家角色维护', 'description' => '维护角色', 'client_type' => 'seller'],
            ['code' => 'seller.setting.staff.view', 'name' => '卖家员工查看', 'description' => '查看员工', 'client_type' => 'seller'],
            ['code' => 'seller.setting.staff.manage', 'name' => '卖家员工维护', 'description' => '维护员工', 'client_type' => 'seller'],
        ];
    }

    private function roles(): array
    {
        return [
            [
                'name' => '管理员',
                'slug' => 'admin',
                'scope_type' => 'system',
                'description' => '系统管理员，拥有全部权限',
            ],
            [
                'name' => '客服',
                'slug' => 'support',
                'scope_type' => 'system',
                'description' => '客服角色，负责任务中心、邀请、物流调度',
            ],
            [
                'name' => '卖家管理员',
                'slug' => 'seller_admin',
                'scope_type' => 'seller',
                'description' => '卖家组织管理员，拥有卖家端全部权限',
            ],
        ];
    }

    private function rolePermissionMap(): array
    {
        $allAdminCodes = array_map(static fn($permission) => $permission['code'], $this->permissions());

        return [
            'admin' => $allAdminCodes,
            'support' => [
                'admin.support.task.view',
                'admin.support.task.assign',
                'admin.support.invite.view',
                'admin.support.invite.manage',
                'admin.order.main.view',
                'admin.order.pickup.view',
                'admin.order.pickup.update',
                'admin.order.refund.view',
                'admin.finance.settlement.view',
                'admin.tms.express.view',
                'admin.tms.express.manage',
            ],
            'seller_admin' => [
                'seller.trade.spotcheck.view',
                'seller.trade.spotcheck.manage',
                'seller.trade.future.view',
                'seller.trade.future.manage',
                'seller.trade.order_delivery.view',
                'seller.trade.order_delivery.manage',
                'seller.product.list.view',
                'seller.product.list.manage',
                'seller.product.upload.view',
                'seller.product.upload.manage',
                'seller.fund.statement.view',
                'seller.fund.statement.manage',
                'seller.setting.role.view',
                'seller.setting.role.manage',
                'seller.setting.staff.view',
                'seller.setting.staff.manage',
            ],
        ];
    }

    private function seedAdminUser(?int $adminRoleId, array $permissionMap): void
    {
        if ($adminRoleId === null) {
            return;
        }

        $now = date('Y-m-d H:i:s');
        $phone = '18596259217';
        $password = password_hash('123456@Aa', PASSWORD_BCRYPT);

        $userId = Db::name('user_account')
            ->where('phone', $phone)
            ->value('id');

        if ($userId) {
            Db::name('user_account')
                ->where('id', (int) $userId)
                ->update([
                    'password_hash' => $password,
                    'status' => 1,
                    'update_time' => $now,
                ]);
        } else {
            $userId = Db::name('user_account')->insertGetId([
                'phone' => $phone,
                'password_hash' => $password,
                'status' => 1,
                'register_channel' => 'system_seed',
                'create_time' => $now,
                'update_time' => $now,
            ]);
        }

        $profile = Db::name('user_profile')->where('user_id', $userId)->find();
        if ($profile) {
            Db::name('user_profile')->where('user_id', $userId)->update([
                'nickname' => '系统管理员',
                'real_name' => '系统管理员',
                'update_time' => $now,
            ]);
        } else {
            Db::name('user_profile')->insert([
                'user_id' => $userId,
                'nickname' => '系统管理员',
                'real_name' => '系统管理员',
                'avatar' => '',
                'gender' => 0,
                'extra' => null,
                'create_time' => $now,
                'update_time' => $now,
            ]);
        }

        $auth = Db::name('user_auth')
            ->where('identity_type', 'password')
            ->where('identifier', $phone)
            ->find();
        if ($auth) {
            Db::name('user_auth')
                ->where('id', (int) $auth['id'])
                ->update([
                    'user_id' => $userId,
                    'credential' => $password,
                    'status' => 1,
                    'update_time' => $now,
                ]);
        } else {
            Db::name('user_auth')->insert([
                'user_id' => $userId,
                'identity_type' => 'password',
                'identifier' => $phone,
                'credential' => $password,
                'metadata' => json_encode([], JSON_UNESCAPED_UNICODE),
                'status' => 1,
                'create_time' => $now,
                'update_time' => $now,
            ]);
        }

        Db::name('auth_user_role')
            ->where('user_id', $userId)
            ->where('role_id', $adminRoleId)
            ->delete();

        Db::name('auth_user_role')->insert([
            'user_id' => $userId,
            'role_id' => $adminRoleId,
            'status' => 1,
            'create_time' => $now,
            'update_time' => $now,
        ]);
    }
}
